<!DOCTYPE html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <meta charset="UTF-8">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="wct-browser-config.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>

  <script type="module" src="../../polymer-legacy.js"></script>
  <script type="module" src="./events-elements.js"></script>
</head>
<body>

  <script type="module">
import './events-elements.js';
import { afterNextRender } from '../../lib/utils/render-status.js';
suite('Event Listeners', function() {
  var el;

  suite('listeners block', function() {
    suiteSetup(function() {
      el = document.createElement('x-listeners');
      document.body.appendChild(el);
    });

    suiteTeardown(function() {
      document.body.removeChild(el);
    });

    test('fire - method exists', function() {
      el.fire('foo');
      assert.equal(el._handled[el.localName], 'foo');
    });

    test('fire - method missing', function() {
      sinon.spy(console, 'warn');
      el.fire('bar');
      assert.isTrue(console.warn.calledOnce);
      assert.equal(console.warn.getCall(0).args[0], 'listener method `missing` not defined');
      console.warn.restore();
    });

  });

  suite('on-*', function() {

    var options;
    suiteSetup(function() {
      el = document.createElement('x-on');
      document.body.appendChild(el);
      options = {node: el.$.inner};
    });

    suiteTeardown(function() {
      document.body.removeChild(el);
    });

    test('fire - method exists', function() {
      el.fire('foo', {}, options);
      assert.equal(el._handled.div, 'foo');
      assert(!el._handled[el.localName]);
    });

    test('fire - method missing', function() {
      sinon.spy(console, 'warn');
      el.fire('bar', {}, options);
      assert.isTrue(console.warn.calledOnce);
      assert.equal(console.warn.getCall(0).args[0], 'listener method `missing` not defined');
      console.warn.restore();
    });

  });

  suite('listeners + on-*', function() {
    suiteSetup(function() {
      el = document.createElement('x-order');
      document.body.appendChild(el);
    });

    suiteTeardown(function() {
      document.body.removeChild(el);
    });

    test('listeners handled before on-* events', function() {
      const e = el.$.inner.fire('foo', {});
      assert.deepEqual(e._handleOrder, ['x-listeners', 'x-order']);
    });

  });

  suite('dynamic', function() {

    var options;
    suiteSetup(function(done) {
      el = document.createElement('x-dynamic');
      document.body.appendChild(el);
      afterNextRender(null, function() {
        options = {node: el.$.inner};
        done();
      });
    });

    suiteTeardown(function() {
      document.body.removeChild(el);
    });

    test('setup', function() {
      assert(!el.__boundListeners, 'listeners are not bound');
      el.setup();
      var boundListeners = el.__boundListeners;
      assert(boundListeners, 'listeners are bound');
      var outerMap = boundListeners.get(el);
      assert(outerMap, 'element events have handlers');
      var innerMap = boundListeners.get(el.$.inner);
      assert(innerMap, 'inner div events have handlers');
    });

    test('fire - method exists', function() {
      el.fire('foo', {}, options);
      assert.equal(el._handled.div, 'foo', 'inner handler');
      assert.equal(el._handled[el.localName], 'foo', 'outer handler');
    });

    test('fire - method missing', function() {
      sinon.spy(console, 'warn');
      el.fire('bar', {}, options);
      assert.isTrue(console.warn.calledTwice);
      assert.equal(console.warn.getCall(0).args[0], 'listener method `missing` not defined');
      assert.equal(console.warn.getCall(1).args[0], 'listener method `missing` not defined');
      console.warn.restore();
    });

    test('teardown', function() {
      el.teardown();
      assert.deepEqual(el._removed[0], {target: el.localName, event: 'foo'});
      assert.deepEqual(el._removed[1], {target: 'div', event: 'foo'});
      assert.deepEqual(el._removed[2], {target: el.localName, event: 'bar'});
      assert.deepEqual(el._removed[3], {target: 'div', event: 'bar'});
    });
  });

  suite('Event Listener Cache', function() {
    suiteSetup(function() {
      el = document.createElement('x-double');
      el.setup();
      document.body.appendChild(el);
    });

    suiteTeardown(function() {
      document.body.removeChild(el);
    });

    test('Event handler fires only once', function() {
      el.fire('foo');
      assert.isTrue(el.fooChanged.calledOnce, 'event should fire only once');
    });

    test('once unlistened, no handler fire', function() {
      el.teardown();
      el.fire('foo');
      assert.isTrue(el.fooChanged.calledOnce, 'event should not be handled anymore');
    });
  });
});
</script>

</body>
</html>
